]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
dnd: Prevent simultaneous DnD operations from happening
authorCarlos Garnacho <carlosg@gnome.org>
Mon, 10 Sep 2018 15:57:34 +0000 (17:57 +0200)
committerFlorian Müllner <florian.muellner@gmail.com>
Sat, 26 Jan 2019 23:38:50 +0000 (23:38 +0000)
Besides the device grab on the drag device, also set up a captured-event
handler to catch other devices (except the keyboard) while the DnD
operation is ongoing. This makes DnD operations exclusive to others.

Also, disallow it in less aggressive ways if maybeStartDrag() gets called
while there is a current draggable.

This might definitely be nicer (eg. having other grabbed devices emit
leave/end events), but can't be done without major surgery to Clutter.

js/ui/dnd.js

index 23af7ba95e31d90df991be9bee08fa439c07c4a7..8bffeb4088352d82753153c4ceec26f940e1dab1 100644 (file)
@@ -109,6 +109,7 @@ var _Draggable = class _Draggable {
         this._dragCancellable = true;
 
         this._eventsGrabbed = false;
+        this._capturedEventId = 0;
     }
 
     _onButtonPress(actor, event) {
@@ -154,9 +155,22 @@ var _Draggable = class _Draggable {
 
         this._grabbedDevice = pointer;
         this._touchSequence = touchSequence;
+
+        this._capturedEventId = global.stage.connect('captured-event', (actor, event) => {
+            let device = event.get_device();
+            if (device != this._grabbedDevice &&
+                device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
+                return Clutter.EVENT_STOP;
+            return Clutter.EVENT_PROPAGATE;
+        });
     }
 
     _ungrabDevice() {
+        if (this._capturedEventId != 0) {
+            global.stage.disconnect(this._capturedEventId);
+            this._capturedEventId = 0;
+        }
+
         if (this._touchSequence)
             this._grabbedDevice.sequence_ungrab (this._touchSequence);
         else
@@ -215,6 +229,13 @@ var _Draggable = class _Draggable {
     },
 
     _onEvent(actor, event) {
+        let device = event.get_device();
+
+        if (this._grabbedDevice &&
+            device != this._grabbedDevice &&
+            device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
+            return Clutter.EVENT_PROPAGATE;
+
         // We intercept BUTTON_RELEASE event to know that the button was released in case we
         // didn't start the drag, to drop the draggable in case the drag was in progress, and
         // to complete the drag and ensure that whatever happens to be under the pointer does
@@ -422,7 +443,8 @@ var _Draggable = class _Draggable {
 
         // See if the user has moved the mouse enough to trigger a drag
         let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
-        if ((Math.abs(stageX - this._dragStartX) > threshold ||
+        if (!currentDraggable &&
+            (Math.abs(stageX - this._dragStartX) > threshold ||
              Math.abs(stageY - this._dragStartY) > threshold)) {
             this.startDrag(stageX, stageY, event.get_time(), this._touchSequence, event.get_device());
             this._updateDragPosition(event);